package com.anonymous.util.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import com.anonymous.util.ConfidentialitySecurityUtils;

public class ServerKeyGen {

	/**
	 * @param args
	 * @throws NoSuchPaddingException 
	 * @throws NoSuchAlgorithmException 
	 * @throws InvalidKeySpecException 
	 * @throws IOException 
	 */
	public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, IOException {
		// TODO Auto-generated method stub
		ConfidentialitySecurityUtils confidentialitySecurityUtils = new ConfidentialitySecurityUtils();
		KeyPair keyPair = confidentialitySecurityUtils.generateCustomKeyPair();
		
		// obtain private and public keys
		PrivateKey privateKey = keyPair.getPrivate();
		PublicKey publicKey = keyPair.getPublic();
		
		// obtain bytes of keys
        KeyFactory keyFactory1 = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec publKeySpec1 = keyFactory1.getKeySpec(publicKey, java.security.spec.X509EncodedKeySpec.class);
        PKCS8EncodedKeySpec privKeySpec1 = keyFactory1.getKeySpec(privateKey, java.security.spec.PKCS8EncodedKeySpec.class);
        byte[] privateKeyBytes = privKeySpec1.getEncoded();
		byte[] publicKeyBytes = publKeySpec1.getEncoded();
				
		// create output streams
		FileOutputStream publicKeyOutputStream = new FileOutputStream(
		"rsa_server_public.bin");
		FileOutputStream privateKeyOutputStream = new FileOutputStream(
		"rsa_server_private.bin");

		// write bytes to files
		privateKeyOutputStream.write(privateKeyBytes);
		publicKeyOutputStream.write(publicKeyBytes);
		
	}
	
	public static PublicKey readPublicKeyFromFile(String fileName) throws Exception {
		byte[] publicKeyBytes = getBytesFromFile(fileName);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKeyBytes);
		PublicKey publicKey = keyFactory.generatePublic(pubKeySpec);
		return publicKey;
	}


	public static PrivateKey readPrivateKeyFromFile(String fileName) throws Exception {
		byte[] privateKeyBytes = getBytesFromFile(fileName);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
		PrivateKey privateKey = keyFactory.generatePrivate(priKeySpec);
		return privateKey;
	}
	
	
	// converts from file to byte array
	public static byte[] getBytesFromFile(String fileName) throws Exception {
		// create file from filename
		File file = new File(fileName);

		// create inputstream of file
		InputStream is = new FileInputStream(file);

		// get filesize
		long length = file.length();

		// make sure file is not larger than Integer.MAX_VALUE.
		if (length > Integer.MAX_VALUE) {
			// file is too big
		}

		// define byte array to hold bytes
		byte[] bytes = new byte[(int) length];

		// read in the bytes
		int offset = 0;
		int numRead = 0;
		while (offset < bytes.length
				&& (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
			offset += numRead;
		}

		// make sure all bytes have been read in
		if (offset < bytes.length) {
			throw new IOException("Error reading file");
		}
		
		// clean up
		is.close();

		// return bytes
		return bytes;
	}
	public static Map<String,SecretKey> SSL4KeysGen(byte [] PMS, byte[] nonce) throws NoSuchAlgorithmException{
		MessageDigest msMessageDigest = MessageDigest.getInstance("SHA-512");
		msMessageDigest.update(PMS);
		msMessageDigest.update(nonce);
		byte[] MS1 = msMessageDigest.digest();
		
        int keyLength = msMessageDigest.getDigestLength()/4;
        byte[] cek = new byte[keyLength];
        byte[] sek = new byte[keyLength];
        byte[] cmk = new byte[keyLength];
        byte[] smk = new byte[keyLength];
        for(int i = 0; i <keyLength; i++){
        	cek[i] = MS1[i];
        	sek[i] = MS1[i+keyLength];
        	cmk[i] = MS1[i+keyLength*2];
        	smk[i] = MS1[i+keyLength*3];
        }

        SecretKey serverSessionKey = new SecretKeySpec(sek, "AES");
        SecretKey clientSessionKey = new SecretKeySpec(cek, "AES");
        SecretKey serverMACKey = new SecretKeySpec(smk, "HmacSHA256");
        SecretKey clientMACKey = new SecretKeySpec(cmk, "HmacSHA256");
        
        Map<String,SecretKey> keyMap = new HashMap<String,SecretKey>();
        keyMap.put("serverSessionKey", serverSessionKey);
        keyMap.put("clientSessionKey", clientSessionKey);
        keyMap.put("serverMACKey", serverMACKey);
        keyMap.put("clientMACKey", clientMACKey);
        return keyMap;
		
		
	}
	
}
